import { columnProps, tryGetJavaApiFile, stackStyles, stackTokens, camelToKebab, getServer2Path, ensureDirectoryExists, copyPackageTools, isIgnoreFolder } from "../utils";

import {
    PrimaryButton,
    MessageBar,
    MessageBarType,
    Stack
} from '@fluentui/react';
import useNameInput from "../Commons/useNameInput";
import useInstallPath from "../Commons/useInstallPath";
import usePluginInstallPath from "../Commons/usePluginInstallPath";
import { fs, path } from '@tauri-apps/api';
import { GlobalContext } from "../Context/global";
import { useContext } from "react";
import usePackageClassInput from "../Commons/usePackageClassInput";
import { RS } from "../../i18n/config";
const API_NAME = 'forguncy-security-provider';
const TEMPLATE_FILE_WHITE_LIST: { [key: string]: true } = {
    "Config.java": true,
    "SECURITY_PROVIDER_NAME.java": true,
    "version.json": true,
    "pom.xml": true,
}
function SecurityProvider() {

    const { dispatch } = useContext(GlobalContext);
    const [PackageClassDom, packageClass, packageNameIsValid] = usePackageClassInput();
    const create = async () => {
        const sourceCodeInstallPath = await path.join(fullInstallPath, name);
        try {
            await ensureDirectoryExists(sourceCodeInstallPath);
            const packagePath = await path.join(sourceCodeInstallPath, "src", "main", "java", ...packageClass.split('.'));
            await ensureDirectoryExists(packagePath);

            const thePath = await path.join(await path.resourceDir(), "security-provider-template");
            await copyFilesRecursively(thePath, sourceCodeInstallPath, name, jarVersion, forguncyPath, packagePath, packageClass, thePath);
            await copyPackageTools(fullInstallPath);
        } catch (error: any) {
            dispatch?.({ type: 'errorMsg', payload: error.toString() });
            return;
        }
        dispatch?.({ type: 'createSuccess', payload: sourceCodeInstallPath })
    }
    const [nameDom, name, nameValid] = useNameInput({ label: RS.Security_Provider, initValue: 'CustomSecurityProvider' });
    const [forguncyInstallPathDom, forguncyPath, forguncyPathValid, jarVersion, _setForguncyPath] = useInstallPath({
        getDependenceVersion: tryGetJavaApiFile,
        apiName: API_NAME
    })
    const [pluginInstallDom, installPath, installPathValid] = usePluginInstallPath({ label: RS.Security_Provider, defaultPath: "forguncy-java-security-provider" });
    const allValid = nameValid && forguncyPathValid && installPathValid && packageNameIsValid;
    const fullInstallPath = `${installPath}${name}`;
    return <div className="container">
        <form noValidate autoComplete="off">
            <Stack horizontal tokens={stackTokens} styles={stackStyles}>
                <Stack {...columnProps}>
                    {nameDom}
                    {PackageClassDom}
                    {forguncyInstallPathDom}
                    {pluginInstallDom}
                    {(!(allValid)) ? undefined : <MessageBar
                        messageBarType={MessageBarType.success}
                        isMultiline={true}
                    >
                        {RS.Project_Will_Be_Created_In}{fullInstallPath}
                    </MessageBar>}
                </Stack>
            </Stack>
        </form>
        <div style={{ textAlign: 'center' }}>
            <PrimaryButton onClick={create} disabled={!(allValid)} style={{ margin: '36px 24px', width: '240px' }}>{RS.Create_Security_Provider}</PrimaryButton>
        </div>
    </div>
}
export default SecurityProvider;



async function copyFilesRecursively(sourcePath: string, targetPath: string, name: string, jarVersion: string, forguncyPath: string, packagePath: string, packageClass: string, root: string) {

    if (!(await fs.exists(sourcePath))) {
        return;
    }

    if (!(await fs.exists(targetPath))) {
        await fs.createDir(targetPath);
    }

    const files = await fs.readDir(sourcePath);

    files.forEach(async (file) => {
        const currentSource = await path.join(sourcePath, file.name || '');
        const currentTarget = await path.join(targetPath, file.name || '');

        const isDir = await getIsDir(currentSource);
        if (isDir) {
            copyFilesRecursively(currentSource, currentTarget, name, jarVersion, forguncyPath, packagePath, packageClass, root);
        } else {
            if (await isIgnoreFolder(file, root) || !TEMPLATE_FILE_WHITE_LIST[file.name || '']) {
            } else if (file.name === 'SECURITY_PROVIDER_NAME.java') {
                //主类的文件名 
                const uint8Array = await fs.readBinaryFile(currentSource);
                const decoder = new TextDecoder('utf-8');
                const decodedString = decoder.decode(uint8Array);
                const targetString = decodedString.replace(/SECURITY_PROVIDER_NAME/g, name).replace(/ORG_EXAMPLE/g, packageClass);
                const newTarget = await path.join(packagePath, name + '.java');
                await fs.writeTextFile(newTarget, targetString);
            } else if (file.name === 'Config.java') {
                //配置文件
                const uint8Array = await fs.readBinaryFile(currentSource);
                const decoder = new TextDecoder('utf-8');
                const decodedString = decoder.decode(uint8Array);
                const targetString = decodedString.replace(/ORG_EXAMPLE/g, packageClass);
                const newTarget = await path.join(packagePath, file.name);
                await fs.writeTextFile(newTarget, targetString);
            } else if (file.name === 'pom.xml') {
                const uint8Array = await fs.readBinaryFile(currentSource);
                const decoder = new TextDecoder('utf-8');
                const decodedString = decoder.decode(uint8Array);
                const jarPath = (await path.join(forguncyPath, await getServer2Path(forguncyPath), 'javaAdapterServerBin')).split("\\").join("/");
                const javaPath = (await path.join(forguncyPath, await getServer2Path(forguncyPath), 'bpmJavaServerBin')).split("\\").join("/");
                const targetString = decodedString.replace(/SECURITY_PROVIDER_NAME/g, camelToKebab(name))
                    .replace(/SECURITY_PROVIDER_DEP_VERSION/g, jarVersion)
                    .replace(/PLUGIN_ABS_PATH/g, jarPath)
                    .replace(/JAVA_PATH/g, javaPath);
                await fs.writeTextFile(currentTarget, targetString); //  pom 改 artifactId name
            } else if (file.name === 'version.json') {
                const uint8Array = await fs.readBinaryFile(currentSource);
                const decoder = new TextDecoder('utf-8');
                const decodedString = decoder.decode(uint8Array);
                const targetString = decodedString.replace(/SECURITY_PROVIDER_DEP_VERSION/g, jarVersion);
                await fs.writeTextFile(currentTarget, targetString); //  versionJson改version
            } else {
                await fs.copyFile(currentSource, currentTarget);
            }
        }
    });

    async function getIsDir(currentSource: string) {
        try {
            await fs.readDir(currentSource);
            return true;
        } catch (error) {
            return false;
        }
    }
}